package com.frontop.terminal.gangedsocket.core;

import cn.hutool.core.thread.ThreadUtil;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Objects;

/**
 * <p>
 * 资源回收线程
 * </P>
 *
 * @author :CCC
 * @since :2020-12-08
 **/
@Component
@Data
@ConfigurationProperties(prefix = "heartbeat")
public class Heartbeat {

    /**
     * 心跳消息
     */
    public static final String HEARTBEAT_MSG = "1";
    /**
     * 心跳响应
     */
    public static final String HEARTBEAT_RESPONSE = "0";
    static int heartbeatTime = 0;
    /**
     * 释放标志
     */
    private static boolean release;
    /**
     * 心跳机制开关
     * true：开启
     * false：关闭
     */
    boolean heartbeatMechanism;
    /**
     * 心跳发送频率，单位：秒
     */
    Integer heartbeatSendTime;
    /**
     * 心跳检测频率，单位：秒
     */
    Integer heartbeatDetectionTime;
    /**
     * 允许无响应次数
     */
    Integer numberOfConnectionFailures;

    public static void release() {
        release = true;
    }

    @PostConstruct
    private void start() {
        if (heartbeatMechanism) {
            release = false;

            //心跳发送线程
            HeartbeatSend heartbeatSend = new HeartbeatSend();
            ThreadUtil.execAsync(heartbeatSend);


            //心跳检测线程
            HeartbeatDetection heartbeatDetection = new HeartbeatDetection();
            ThreadUtil.execAsync(heartbeatDetection);

            System.out.println("[播放联动socket服务端]心跳机制启动");
        }
    }

    class HeartbeatSend implements Runnable {

        @Override
        public void run() {
            Long time = 1000L;
            while (ThreadUtil.sleep(time * heartbeatSendTime)) {
                if (release) {
                    System.out.println("[播放联动socket服务端]心跳机制关闭");
                    break;
                }

                if (!PlayGangedServiceSocket.clients.isEmpty()) {
                    for (PlayGangedService socket : PlayGangedServiceSocket.clients) {
                        socket.send("1");
                    }
                }

                heartbeatTime++;
                if (heartbeatTime == 127) {
                    heartbeatTime = 0;
                }
            }
        }
    }

    class HeartbeatDetection implements Runnable {

        @Override
        public void run() {
            Long time = 1000L;
            while (ThreadUtil.sleep(time * heartbeatDetectionTime)) {
                if (release) {
                    break;
                }

                if (!PlayGangedServiceSocket.clients.isEmpty()) {
                    for (PlayGangedService socket : PlayGangedServiceSocket.clients) {
                        Integer heartbeatTime = socket.getHeartbeatTime();
                        Integer numberOfConnection = socket.getNumberOfConnection();

                        if (Objects.nonNull(numberOfConnection) && numberOfConnection.equals(numberOfConnectionFailures)) {
                            socket.release();
                        } else if (Heartbeat.heartbeatTime != 0) {
                            if (Objects.isNull(heartbeatTime) || heartbeatTime != Heartbeat.heartbeatTime) {
                                socket.setNumberOfConnection(null != numberOfConnection ? numberOfConnection + 1 : 1);
                            }
                        }
                    }
                }
            }
        }
    }
}
